package com.ccb.sc.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ccb.sc.order.service.IAppOrderReturnService;
import com.ccb.sc.payment.service.IPaymentService;
//psl import com.ccb.sc.common.bind.exception.BizException;
import com.ccb.sc.common.bind.page.PageParams;
import com.ccb.sc.common.bind.page.PageVo;
import com.ccb.sc.common.code.BizCodeFace;
import com.ccb.sc.common.code.ErrorCode;
import com.ccb.sc.common.enums.AuditStatus;
import com.ccb.sc.common.modules.common.service.IDeliveryService;
import com.ccb.sc.common.modules.common.vo.QueryTrackResp;
import com.ccb.sc.common.modules.goods.entity.Goods;
import com.ccb.sc.common.modules.goods.service.IGoodsService;
import com.ccb.sc.common.modules.order.convert.OrderReturnConvert;
import com.ccb.sc.common.modules.order.entity.Order;
import com.ccb.sc.common.modules.order.entity.OrderItem;
import com.ccb.sc.common.modules.order.entity.OrderRefund;
import com.ccb.sc.common.modules.order.entity.OrderReturn;
import com.ccb.sc.common.modules.order.enums.OrderReturnType;
import com.ccb.sc.common.modules.order.enums.OrderStatus;
import com.ccb.sc.common.modules.order.mapper.OrderMapper;
import com.ccb.sc.common.modules.order.mapper.OrderReturnMapper;
import com.ccb.sc.common.modules.order.service.IOrderItemService;
import com.ccb.sc.common.modules.order.service.impl.OrderRefundService;
import com.ccb.sc.common.modules.order.vo.OrderReturnCreateVo;
import com.ccb.sc.common.modules.order.vo.OrderReturnListVo;
import com.ccb.sc.common.modules.payment.entity.Payment;
import com.ccb.sc.common.modules.setting.service.ISettingsService;
import com.ccb.sc.common.modules.setting.vo.OrderSettingsVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author gs.li
 * @version 1.0
 * @date 2020/11/18 15:40
 */
@Slf4j
@Service
public class AppOrderReturnServiceImpl extends ServiceImpl<OrderReturnMapper, OrderReturn> implements IAppOrderReturnService {

    private OrderMapper orderMapper;
    private IOrderItemService orderItemService;
    private IDeliveryService deliveryService;
    private ISettingsService settingsService;
    private IPaymentService paymentService;
    private OrderRefundService orderRefundService;
    private IGoodsService goodsService;

    @Override
    public PageVo<OrderReturnListVo> list(Long memberId, PageParams queryParam) {
        Page<OrderReturn> page = new Page<>(queryParam.getCurrent(), queryParam.getPageSize());
        page.setOrders(Lists.newArrayList(com.baomidou.mybatisplus.core.metadata.OrderItem.desc("create_time")));
        QueryWrapper<OrderReturn> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(OrderReturn::getMemberId, memberId);
        Page<OrderReturn> resultPage = this.getBaseMapper().selectPage(page, queryWrapper);
        if (CollectionUtils.isEmpty(resultPage.getRecords())) {
            return PageVo.create(queryParam.getCurrent(), queryParam.getPageSize(), 0, Lists.newArrayList());
        }
        List<OrderReturnListVo> resultList = resultPage.getRecords()
                .stream()
                .map(OrderReturnConvert.INSTANCE::entity2ListVo)
                .collect(Collectors.toList());
        return PageVo.create(queryParam.getCurrent(), queryParam.getPageSize(), resultPage.getTotal(), resultList);
    }

    @Override
    public void returnGoods(Long memberId, OrderReturnCreateVo createVo) {
        // todo 加锁
        // 判断订单状态
        Order order = this.orderMapper.selectById(createVo.getOrderId());
        Assert.isTrue(order != null && order.getMemberId().equals(memberId), "订单不存在");
        Assert.isTrue(!OrderStatus.WAIT_PAY.equals(order.getStatus()), "订单未付款");
        OrderSettingsVo orderSettings = this.settingsService.getSettings(OrderSettingsVo.class);

        if (order.getStatus() == OrderStatus.FINISHED && order.getFinishTime() != null && order.getFinishTime()
                .plusDays(Optional.ofNullable(orderSettings.getAfterSaleDays()).orElse(7))
                .compareTo(LocalDateTime.now()) < 0) {
            //psl throw new BizException(BizCodeFace.createBizCode(ErrorCode.DATE_NULL).message("订单已过售后期，清联系客服"));
        }

        OrderItem orderItem = this.orderItemService.getById(createVo.getOrderItemId());
        Assert.isTrue(orderItem != null && order.getId().equals(orderItem.getOrderId()), "订单不存在");
        Assert.isTrue(orderItem.getQuantity() - orderItem.getReturnQuantity() >= createVo.getQuantity() , "退货退款数量大于可申请数量");

        OrderReturn orderReturn = OrderReturnConvert.INSTANCE.createVo2Entity(createVo);
        BigDecimal refundAmount = orderItem.getPrice().multiply(new BigDecimal(createVo.getQuantity()));
        orderReturn.setOrderAmount(order.getAmount());
        orderReturn.setRefundAmount(refundAmount);
        orderReturn.setGoodsName(orderItem.getGoodsName());
        orderReturn.setGoodsSpec(orderItem.getGoodsSpec());
        if (!StringUtils.hasText(orderItem.getPicture())) {
            Goods goods = this.goodsService.getById(orderItem.getGoodsId());
            orderReturn.setPicture(goods.getPicture());
        }else {
            orderReturn.setPicture(orderItem.getPicture());
        }
        orderReturn.setMemberId(memberId);
        orderReturn.setAuditStatus(AuditStatus.WAITAUDIT);
        boolean result = this.save(orderReturn);
        if (!result) {
            //psl throw new BizException(BizCodeFace.createBizCode(ErrorCode.FAIL));
        }

        orderItem.setReturnQuantity(orderItem.getReturnQuantity() + createVo.getQuantity());
        this.orderItemService.updateById(orderItem);

        if (createVo.getReturnType() == OrderReturnType.EXCHANGE.getValue()) {
            return;
        }

        BigDecimal ratio = refundAmount.divide(order.getAmount(), 2, RoundingMode.HALF_UP);
        if (ratio.compareTo(BigDecimal.ONE) > 0) {
            log.error("退款订单异常，订单项金额大于总订单金额：订单id：{}，退款订单id：{}", order.getId(), orderReturn.getId());
            //psl throw new BizException(BizCodeFace.createBizCode(ErrorCode.DATE_NULL).message("退换订单异常"));
        }
        // 生成退款单
        OrderRefund orderRefund = new OrderRefund();
        orderRefund.setOrderReturnId(orderReturn.getId());
        orderRefund.setOrderId(order.getId());
        orderRefund.setMemberId(memberId);
        orderRefund.setReason(createVo.getReason());
        orderRefund.setMemo(createVo.getMemo());
        orderRefund.setStatus(AuditStatus.WAITAUDIT);
        //计算退还积分
        if (order.getUsePoints().compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal returnPoints = order.getUsePoints().multiply(ratio);
            orderRefund.setPoints(returnPoints.intValue());
        }
        //计算退还余额
        if (order.getWalletDeductAmount().compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal returnWalletAmount = order.getWalletDeductAmount().multiply(ratio);
            orderRefund.setWalletAmount(returnWalletAmount);
        }
        //计算退还实付金额
        if (order.getRealAmount().compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal refundPayAmount = order.getRealAmount().multiply(ratio);
            orderRefund.setPayAmount(refundPayAmount);
            // 查找支付信息
            Payment payment = this.paymentService.getByOrderId(order.getId());
            orderRefund.setPaymentMethod(payment.getPaymentMethod());
            orderRefund.setPaymentPluginId(payment.getPaymentPluginId());
        }
        this.orderRefundService.save(orderRefund);
    }

    @Override
    public OrderReturnListVo detail(Long memberId, Long orderReturnId) {
        OrderReturn orderReturn = this.getById(orderReturnId);
        if (orderReturn == null) {
            return null;
        }
        Assert.isTrue(Objects.equals(orderReturn.getMemberId(), memberId), "数据不存在！");
        return OrderReturnConvert.INSTANCE.entity2ListVo(orderReturn);
    }

    public QueryTrackResp orderTrace(Long orderReturnId) {
        OrderReturn orderReturn = this.getById(orderReturnId);
        Assert.notNull(orderReturn, "订单不存在");
        if (!StringUtils.hasText(orderReturn.getLogisticsCompany()) || !StringUtils.hasText(orderReturn.getLogisticsNo())) {
            return null;
        }
        Order order = this.orderMapper.selectById(orderReturn.getOrderId());
        return this.deliveryService.queryTrack(orderReturn.getLogisticsCompany(), orderReturn.getLogisticsNo(), order.getPhone());
    }

    @Autowired
    public void setOrderMapper(OrderMapper orderMapper) {
        this.orderMapper = orderMapper;
    }

    @Autowired
    public void setOrderItemService(IOrderItemService orderItemService) {
        this.orderItemService = orderItemService;
    }

    @Autowired
    public void setDeliveryService(IDeliveryService deliveryService) {
        this.deliveryService = deliveryService;
    }

    @Autowired
    public void setSettingsService(ISettingsService settingsService) {
        this.settingsService = settingsService;
    }

    @Autowired
    public void setPaymentService(IPaymentService paymentService) {
        this.paymentService = paymentService;
    }

    @Autowired
    public void setOrderRefundService(OrderRefundService orderRefundService) {
        this.orderRefundService = orderRefundService;
    }

    @Autowired
    public void setGoodsService(IGoodsService goodsService) {
        this.goodsService = goodsService;
    }
}
